#include "user_pwm.h"
#include "driver/gpio.h"
#include "driver/ledc.h"
#include "driver/timer.h"
#include "app.h"
#include "driver/gptimer.h"

#define BREATIME 500

#define FULL_EV_BIT BIT0
#define EMPTY_EV_BIT BIT1

#define PWM_P GPIO_NUM_27
#define PWM_N GPIO_NUM_14
#define PWM_ADJ GPIO_NUM_12
#define PWM_TEMP GPIO_NUM_26

#define PWM_CHANNEL_P LEDC_CHANNEL_2
#define PWM_CHANNEL_N LEDC_CHANNEL_3
#define PWM_CHANNEL_ADJ LEDC_CHANNEL_0
#define PWM_CHANNEL_TEMP LEDC_CHANNEL_1

#define MAX_DUTY 262143

extern tSys_Status Sys_Status;
extern tSys_Flag Sys_Flag;

static const char *TAG = "user_pwm";

void Configure_PWM_Gpio(void)
{
    gpio_config_t gpio_cfg =
        {
            .pin_bit_mask = (1 << PWM_P) | (1 << PWM_N) | (1 << PWM_ADJ) | (1 << PWM_TEMP),
            .pull_down_en = GPIO_PULLDOWN_ENABLE,
            .pull_up_en = GPIO_PULLUP_DISABLE,
            .mode = GPIO_MODE_OUTPUT,
            .intr_type = GPIO_INTR_DISABLE,
        };

    gpio_config(&gpio_cfg);
}

void Configure_Pwm(void)
{
    // 设置pwm功能的定时器为定时器0,给温控及电压控制
    ledc_timer_config_t led_pwm_cfg1 =
        {
            .speed_mode = LEDC_LOW_SPEED_MODE,
            .timer_num = LEDC_TIMER_0,
            .clk_cfg = LEDC_AUTO_CLK,
            .freq_hz = 5000,
            .duty_resolution = LEDC_TIMER_8_BIT,
        };

    ledc_timer_config(&led_pwm_cfg1);

    // 设置pwm功能的定时器为定时器1,给变压器P / N
    ledc_timer_config_t led_pwm_cfg2 =
        {
            .speed_mode = LEDC_HIGH_SPEED_MODE,
            .timer_num = LEDC_TIMER_1,
            .clk_cfg = LEDC_AUTO_CLK,
            .freq_hz = 50,
            .duty_resolution = LEDC_TIMER_18_BIT,
        };

    ledc_timer_config(&led_pwm_cfg2);


    // 电压控制
    ledc_channel_config_t ledc_channel1 = {
        .speed_mode = LEDC_LOW_SPEED_MODE,
        .channel = PWM_CHANNEL_ADJ,
        .timer_sel = LEDC_TIMER_0,
        .gpio_num = PWM_ADJ,
        .duty = 0,
        .intr_type = LEDC_INTR_DISABLE,
    };
    ledc_channel_config(&ledc_channel1);

    // 温度控制
    ledc_channel_config_t ledc_channel2 = {
        .speed_mode = LEDC_LOW_SPEED_MODE,
        .channel = PWM_CHANNEL_TEMP,
        .timer_sel = LEDC_TIMER_0,
        .gpio_num = PWM_TEMP,
        .duty = 0,
        .intr_type = LEDC_INTR_DISABLE,
    };
    ledc_channel_config(&ledc_channel2);

    // 变压器 P 
    ledc_channel_config_t ledc_channel3 = {
        .speed_mode = LEDC_HIGH_SPEED_MODE,
        .channel = PWM_CHANNEL_P,
        .timer_sel = LEDC_TIMER_1,
        .gpio_num = PWM_P,
        .duty = 0,
        .intr_type = LEDC_INTR_DISABLE,
    };
    ledc_channel_config(&ledc_channel3);

    // 变压器 N 
    ledc_channel_config_t ledc_channel4 = {
        .speed_mode = LEDC_HIGH_SPEED_MODE,
        .channel = PWM_CHANNEL_N,
        .timer_sel = LEDC_TIMER_1,
        .gpio_num = PWM_N,
        .duty = 0,
        .hpoint = (1 << (led_pwm_cfg2.duty_resolution))  /2,
        .intr_type = LEDC_INTR_DISABLE,
    };
    ledc_channel_config(&ledc_channel4);

    ledc_set_duty(LEDC_LOW_SPEED_MODE , PWM_CHANNEL_ADJ ,20);
    ledc_update_duty(LEDC_LOW_SPEED_MODE , PWM_CHANNEL_ADJ ) ;

    //gptimer_set_raw_count(LEDC_TIMER_1 , 0);
    ledc_set_duty(LEDC_HIGH_SPEED_MODE , PWM_CHANNEL_P ,0);
    ledc_update_duty(LEDC_HIGH_SPEED_MODE , PWM_CHANNEL_P ) ;

    
    //gptimer_set_raw_count(LEDC_TIMER_2 , 0);
    ledc_set_duty(LEDC_HIGH_SPEED_MODE , PWM_CHANNEL_N ,0);
    ledc_update_duty(LEDC_HIGH_SPEED_MODE , PWM_CHANNEL_N ) ;
}

/// @brief 功能函数：设置设备工作模式。
/// @param adj_num 源电压设置占空比 0~255
/// @param frequency   设备工作频率
/// @param timer_cont   周期内工作时长
/// @param max_cont     工作周期最大值
/// @param amp_num      步进大小

void change_mode_process(int adj_num , int frequency , int timer_cont , int max_cont ,int amp_num)
{
    int  duty_resolution= 0;
/////////////////  切换模式时， 先全部关闭当前的波形输出和电压值。 ///////////////////////
    ledc_set_duty(LEDC_HIGH_SPEED_MODE, PWM_CHANNEL_P, 0);
    ledc_update_duty(LEDC_HIGH_SPEED_MODE, PWM_CHANNEL_P);
    ledc_set_duty(LEDC_HIGH_SPEED_MODE, PWM_CHANNEL_N, 0);
    ledc_update_duty(LEDC_HIGH_SPEED_MODE, PWM_CHANNEL_N);
    ledc_set_duty(LEDC_LOW_SPEED_MODE , PWM_CHANNEL_ADJ ,adj_num);
    ledc_update_duty(LEDC_LOW_SPEED_MODE , PWM_CHANNEL_ADJ ) ;
    Sys_Status.Streng_Value = 0;

    vTaskDelay(200);

    Sys_Status.RealTIme_Frequency = frequency;
    ESP_LOGI(TAG,"Sys_Status.RealTIme_Frequency Value  = %d" ,(int)Sys_Status.RealTIme_Frequency);
    if (Sys_Status.RealTIme_Frequency > 1000)
        duty_resolution = LEDC_TIMER_12_BIT;
    else if ((Sys_Status.RealTIme_Frequency > 100) && (Sys_Status.RealTIme_Frequency <= 1000))
        duty_resolution = LEDC_TIMER_15_BIT;
    else
        duty_resolution = LEDC_TIMER_18_BIT;

    // 设置pwm功能的定时器为定时器1,给变压器P / N
    ledc_timer_config_t led_pwm_cfg2 =
        {
            .speed_mode = LEDC_HIGH_SPEED_MODE,
            .timer_num = LEDC_TIMER_1,
            .clk_cfg = LEDC_AUTO_CLK,
            .freq_hz = frequency,
            .duty_resolution = duty_resolution,
        };
    ledc_timer_config(&led_pwm_cfg2);

    // 变压器 N 的设置， P通道由偏移来进行翻转。
    ledc_channel_config_t ledc_channel4 =
        {
            .speed_mode = LEDC_HIGH_SPEED_MODE,
            .channel = PWM_CHANNEL_N,
            .timer_sel = LEDC_TIMER_1,
            .gpio_num = PWM_N,
            .duty = 0,
            .hpoint = (1 << (led_pwm_cfg2.duty_resolution)) / 2,
            .intr_type = LEDC_INTR_DISABLE,
        };
    ledc_channel_config(&ledc_channel4);

    if (timer_cont <= max_cont && max_cont > 2)  // 限定数值范围
    {
        Sys_Status.Yz_Timer_Cont = timer_cont;
        Sys_Status.Yz_Timer_Cont_ALL = max_cont;
    }

    Sys_Status.Pwm_Amp_Num = amp_num;
}

void pwm_mode1_init(void)
{
    change_mode_process(250 , 30 , 10 , 10, 30);
}

void pwm_mode2_init(void)
{
    change_mode_process(250 , 30 , 6 , 10,30);
}
void pwm_mode3_init(void)
{
    change_mode_process(250 , 50 , 10 ,10, 30);
}
void pwm_mode4_init(void)

{
    change_mode_process(250 , 2000 , 10 ,10, 30);
}

void pwm_mode5_init(void)
{
    change_mode_process(200 , 30 , 10 ,10, 30);
}

char pwm_mode_custom_init(int adj_num , int frequency , int timer_cont , int max_cont ,int amp_num)
{
    if(adj_num < 100 || adj_num > 255) return 1;
    if(frequency < 10 || frequency > 5000) return 1;
    if(timer_cont < 0 || timer_cont > max_cont) return 1;
    if(max_cont < 0 || max_cont > 100) return 1;
    if(amp_num < 1 || amp_num > 80) return 1;

    change_mode_process(adj_num , frequency , timer_cont ,max_cont, amp_num);
    return 0;
}


// 定时器中断处理函数
bool IRAM_ATTR timer_group_isr_callback(void *args) // 100ms 循环
{
    int pwm_duty = 0 ;
    static int old_pwm_duty = 0;
    static int timer_cont = 0;
    // 清除定时器中断标志
    timer_group_clr_intr_status_in_isr(TIMER_GROUP_0, TIMER_0);

    // 重新使能定时器中断
    timer_group_enable_alarm_in_isr(TIMER_GROUP_0, TIMER_0);

    // 更新PWM占空比
    if (Sys_Flag.Led_Start_Flag == 1 && Sys_Flag.System_Power == 1 && Sys_Status.Streng_Value != 0)
    {
        timer_cont ++; if(timer_cont > Sys_Status.Yz_Timer_Cont_ALL) timer_cont = 0;

        if (timer_cont <= Sys_Status.Yz_Timer_Cont)
        {
            if (Sys_Status.RealTIme_Frequency > 1000 )
                pwm_duty = Sys_Status.Streng_Value * 10;
            else if ((Sys_Status.RealTIme_Frequency > 100 )&& (Sys_Status.RealTIme_Frequency <= 1000)) 
                pwm_duty = Sys_Status.Streng_Value * Sys_Status.Streng_Value / 3;
            else 
                pwm_duty = Sys_Status.Streng_Value * (Sys_Status.Pwm_Amp_Num  + Sys_Status.Pwm_Amp_Num  * Sys_Status.Streng_Value / 20); // 依据档位，调整放大倍数，档位越高，倍数越大
            // 
          //  pwm_duty = Sys_Status.Streng_Value * Sys_Status.Streng_Value; // 依据档位，调整放大倍数，档位越高，倍数越大
        }
        else
            pwm_duty = 0;
    }
    else
        pwm_duty = 0;

    // 更新PWM占空比
    if (old_pwm_duty != pwm_duty  && Sys_Status.Streng_Value != 0)
    {
        old_pwm_duty = pwm_duty;
        ledc_set_duty(LEDC_HIGH_SPEED_MODE, PWM_CHANNEL_P, pwm_duty);
        ledc_update_duty(LEDC_HIGH_SPEED_MODE, PWM_CHANNEL_P);
        ledc_set_duty(LEDC_HIGH_SPEED_MODE, PWM_CHANNEL_N, pwm_duty);
        ledc_update_duty(LEDC_HIGH_SPEED_MODE, PWM_CHANNEL_N);
      
        ESP_DRAM_LOGI(TAG,"old_pwm_duty Value DUTY = %d" ,pwm_duty);
    }

    // 返回true表示不需要调用更高优先级的中断处理程序
    return true;
}

void Timer_Init(void)
{
    // 配置定时器
    timer_config_t timer_config = {
        .clk_src = TIMER_SRC_CLK_DEFAULT,
        .divider = 80,
        .counter_dir = TIMER_COUNT_UP,
        .counter_en = TIMER_PAUSE,
        .alarm_en = TIMER_ALARM_EN,
        .auto_reload = TIMER_AUTORELOAD_EN,
    };
    timer_init(TIMER_GROUP_0, TIMER_0, &timer_config);

    // 设置定时器初始值
    timer_set_counter_value(TIMER_GROUP_0, TIMER_0, 0);

    // 设置定时器报警值（1ms）
    timer_set_alarm_value(TIMER_GROUP_0, TIMER_0, 100 * 1000);

    // 注册定时器中断处理函数
    timer_isr_callback_add(TIMER_GROUP_0, TIMER_0, timer_group_isr_callback, NULL, 0);

    // 启动定时器
    timer_start(TIMER_GROUP_0, TIMER_0);
}

SemaphoreHandle_t sem_Pwm_Change;

void Led_Task(void* param)
{
    int value = 0;
    char mode = 0 ,Old_Heat_Value = 0 ;
    Configure_PWM_Gpio();

    Configure_Pwm();
    
    sem_Pwm_Change = xSemaphoreCreateBinary();   // 创建PWM修改信号量

    Timer_Init();
    while (1)
    {
       // 温度判断
        {
            if (Sys_Flag.System_Power == 1)
            {
                switch (Sys_Status.Heat_Value)
                {
                case 0:
                    value = 0;
                    break;
                case 1:
                    if (Sys_Status.Temp_Adc_Value < Heat_Valu_NULL)
                    {
                        value = Heat_Value_NULL_L1;    
                    }
                    else if (Sys_Status.Temp_Adc_Value < Heat_Value_L1)
                        value = 250;
                    else if (Sys_Status.Temp_Adc_Value > Heat_Value_L1)
                        value = 0;
                    break;
                case 2:
                    if (Sys_Status.Temp_Adc_Value < Heat_Valu_NULL)
                    {
                        value = Heat_Value_NULL_L2;
                    }
                    else if (Sys_Status.Temp_Adc_Value < Heat_Value_L2)
                        value = 250;
                    else if (Sys_Status.Temp_Adc_Value > Heat_Value_L2)
                        value = 0;
                    break;
                case 3:
                    if (Sys_Status.Temp_Adc_Value < Heat_Valu_NULL)
                    {
                        value = Heat_Value_NULL_L3;
                    }
                    else if (Sys_Status.Temp_Adc_Value < Heat_Value_L3)
                        value = 250;
                    else if (Sys_Status.Temp_Adc_Value > Heat_Value_L3)
                        value = 0;
                    break;
                }
            }
            else
                value = 0;

            if(Old_Heat_Value != value)
            {
                Old_Heat_Value = value;
                ledc_set_duty(LEDC_LOW_SPEED_MODE, PWM_CHANNEL_TEMP, value); // 温度调节 4档
                ledc_update_duty(LEDC_LOW_SPEED_MODE, PWM_CHANNEL_TEMP);
              //  ESP_LOGI(TAG,"value = %d", (int ) value);
            }
        }

        if(mode != Sys_Status.Mode_Value)
        {
            mode = Sys_Status.Mode_Value;
            switch( mode )
            {
            case 1:
                pwm_mode1_init();
                break;
            case 2:
                pwm_mode2_init();
                break;
            case 3:
                pwm_mode3_init();
                break;
            case 4:
                pwm_mode4_init();
                break;
                // case 5:
                // pwm_mode5_init();
                //break;
            }
        }

       // ESP_LOGI(TAG,"FREE" );
        vTaskDelay(5);
    }
}
